﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.ComponentModel;

namespace XEvents.Library.Targets
{
    public interface ITargetData
    {
        //Properties
        DataTable TargetInfo {get;}
        EventSessionTarget Parent {get;}
        bool HasChanged {get;}

        //Methods
        //void LoadTargetData();
    }

    public delegate void DataTableUpdateEventHandler(object sender, EventArgs e);
    public delegate void LoadStatusChangedEventHandler(object sender, LoadStatusChangedEventArgs e);


    public class LoadStatusChangedEventArgs : EventArgs
    {
        public LoadStatus CurrentStatus{get; set;}             
    }

    public enum LoadStatus
    {
        Initalizing,
        Requesting_Data,
        Processing_Data,
        Completed
    }

    public abstract class TargetData : XEventBase, ITargetData
    {
        internal BackgroundWorker bw = new BackgroundWorker();
        internal DataTable targetinfo = new DataTable();
        internal EventSessionTarget parent;
        internal object locker = new object();
        internal LoadStatus status = LoadStatus.Initalizing;

        public event RunWorkerCompletedEventHandler RunWorkerCompleted;
        public event ProgressChangedEventHandler ProgressChanged;
        public event LoadStatusChangedEventHandler StatusChanged;
        public event DataTableUpdateEventHandler TargetInfoUpdated;

        internal TargetData(SqlServer server, EventSessionTarget parent)
            : base(server)
        { 
            this.parent = parent;

            // background worker setup
            bw.WorkerReportsProgress = true;
            bw.WorkerSupportsCancellation = true;

            bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);
            bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
            bw.DoWork += new DoWorkEventHandler(bw_DoWork);

            bw.RunWorkerAsync();
        }


        protected void TargetInfoChanged()
        {
            EventArgs args = new EventArgs();
            if (this.TargetInfoUpdated != null)
                this.TargetInfoUpdated(this, args);
        }
        protected void ChangeStatus(LoadStatus newstatus)
        {
            if (!(status == newstatus))
            {
                status = newstatus;
                LoadStatusChangedEventArgs args = new LoadStatusChangedEventArgs() { CurrentStatus = newstatus };
                if (this.StatusChanged != null)
                {
                    this.StatusChanged(this, args);
                }
            }
        }          

        void  bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (this.RunWorkerCompleted != null)
            {
                this.RunWorkerCompleted(this, e);
            }        
        }
        void  bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            if (this.ProgressChanged != null)
            {
                this.ProgressChanged(this, e);
            }    
        }
        void bw_DoWork(object sender, DoWorkEventArgs e)
        {
            InitalizeTarget();
            LoadData();
        }

        public void CancelAsync()
        {
            if (bw.IsBusy)
                bw.CancelAsync();
            //while (bw.IsBusy)
                //System.Threading.Thread.Sleep(100);
        }

        protected abstract void InitalizeTarget();
        protected abstract void LoadData();

        //private abstract void InitalizeTarget();
        //private abstract DataTable InitalizeTable();

        public void Refresh()
        {
            bw.RunWorkerAsync();
        }

        public DataTable TargetInfo
        {
            get { return targetinfo; }
        }

        public EventSessionTarget Parent
        {
            get { return parent; }
        }

        public bool HasChanged
        {
            get
            {return false;}
        }

    }
}
